#include <linux/types.h>
#include <linux/ioport.h>
#include <asm/io.h>


typedef unsigned char byte;
#define TIMEOUT 4000000000LL
#define EOT 	4
#define ESC		27

#define ERROR_CHECKSUM 	-1
#define ERROR_LOCKED 	-2
#define ERROR_SENDBITS 	-3

#define WINDOW_SIZE		1024 
#define TRY_COUNT		5

/**
 * Pins :
 * 	1 = data bit 1
 * 	2 = data bit 2
 *	3 = err feedback
 *  	4 = writeStatus
 *	5 = readStatus
 */
typedef struct {
	byte data; 		//2 bit
	byte errFeedback;	//1 bit
	int writeStatus;	//1 bit
	int readStatus;		//1 bit
} CProtocol;

/*
#define ssize_t long
#define size_t unsigned long
*/

//should be called from module_init
void initCProtocol(void);

/**
 * Update value in hardware based on pins
 */
void commitProtocol(CProtocol* p);

/**
 * Update out value based on hardware.
 * out->data should be from pin 1, 2, and 3
 */
void readProtocol(CProtocol* out);

/**
 * Get two bits
 * ex : 
 *	getTwoBits(01110010b, 0) -> 10 
 *	getTwoBits(01110010b, 1) -> 00 
 *	getTwoBits(01110010b, 2) -> 11 
 *	getTwoBits(01110010b, 3) -> 01 
 */
byte getTwoBits(byte from, int idx);
void setTwoBits(byte* from, int idx, byte val);

/**
 * read a byte from hardware, put the byteacter to out, and customData from hardware to outCustomData
 * return 3 if reading succeed
 */
int readAChar(byte* out);

/**
 * write a byte to hardware
 * return 3 if writing succeed
 */
int writeAChar(byte in);

int writeCheckSumAndGetFeedback(byte checkSum, byte* feedBack);

int getCheckSumAndWriteFeedback(byte expectedCheckSum, byte* myFeedback);

/**
 * read characters from hardware until len or end of stream, put the characters to out
 * return the number of characters read
 */
ssize_t readABunch(byte* out, char* foundEOT, size_t len);


/**
 * write characters to hardware as many as len
 * return the number of characters written
 */
ssize_t writeABunch(byte* in, size_t len);

ssize_t readCharSequence(byte* out, char* foundEOT, size_t len);

ssize_t writeCharSequence(byte* in, size_t len);
